package com.eco.fanliapp.admin.controller.web;


import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.eco.fanliapp.admin.annotation.SysLogAnnotation;
import com.eco.fanliapp.admin.common.BaseController;
import com.eco.fanliapp.common.constant.ApiEnum;
import com.eco.fanliapp.common.response.ServerResponse;
import com.eco.fanliapp.dao.SyAdminLoginIpMapper;
import com.eco.fanliapp.entity.*;
import com.eco.fanliapp.admin.security.constant.ConstantKey;
import com.eco.fanliapp.service.*;
import com.eco.fanliapp.utils.MD5Utils;
import com.eco.fanliapp.utils.MapValueHelper;
import com.eco.fanliapp.vo.UserMenuVo;
import com.eco.fanliapp.vo.UserVO;
import com.eco.fanliapp.vo.VerifyCodeVo;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
import java.util.concurrent.TimeUnit;


@RestController
@RequestMapping("/web/administrator")
@Slf4j
public class AdministratorLoginController extends BaseController {
    @Autowired
    private IAdministratorService administratorService;
    @Autowired
    private ISubAccountService subAccountService;
    @Autowired
    private TaoBaoPlanService taoBaoPlanService;
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private SyAdminLoginIpMapper syAdminLoginIpMapper;
    @Autowired
    private ISyAdminLoginIpService syAdminLoginIpService;

    private static String  admin = "admin";


    /**
     * 生成验证码
     * @param request
     * @param response
     * @throws IOException
     */
    @SysLogAnnotation(value = "联盟过期提醒",userType = 2)
    @RequestMapping(method = RequestMethod.GET,value = "/handlerMessage")
    public ServerResponse handlerMessage(HttpServletRequest request, HttpServletResponse response)throws IOException {
        int count = 0;
        List<TaobaoScheme> taoBaoPlanList = taoBaoPlanService.findTaoBaoPlanAll(null);
        StringBuffer str = new StringBuffer();
        for (TaobaoScheme taoBaoPlan: taoBaoPlanList) {
            //到期时间
            long upTime = taoBaoPlan.getExpireTime().getTime();
            //获取剩余时间
            long time = upTime - System.currentTimeMillis();
            if ( time/(24*3600*1000) <= 3){
                //该步即不会第一位有逗号，也防止最后一位拼接逗号！
                if (str.length() > 0) {
                    str.append(",");
                }
                str.append(taoBaoPlan.getTaobaoName());
                count ++;
            }
        }
        if(count > 0){
            //组装消息内容（联盟 + 个数 + 通知）
            String content = str.toString() + count + "个联盟即将到期！";
            return ServerResponse.createBySuccess("通知消息",content);
        }

        return ServerResponse.createBySuccess("通知消息",null);
    }


    /**
     * 生成验证码
     * @param request
     * @param response
     * @throws IOException
     */
    @SysLogAnnotation(value = "生成验证码",userType = 2)
    @RequestMapping(method = RequestMethod.GET,value = "/createVerifyCode")
    public void createVerifyCode(HttpServletRequest request, HttpServletResponse response)throws IOException {
        //创建对象
        VerifyCodeVo vc = new VerifyCodeVo();
        //获取图片对象
        BufferedImage bi = vc.getImage();
        //获得图片的文本内容
        String text = vc.getText();
        // 将系统生成的文本内容保存到redis中，有效期1分钟
        redisTemplate.opsForValue().set("text",text, 60, TimeUnit.SECONDS);//60秒
        //向浏览器输出图片
        vc.output(bi, response.getOutputStream());

    }


    public boolean checkLock(String username) {
        Object o = redisTemplate.opsForValue().get("loginCheckLock" + username);
        if (o == null) {
            return true;
        }
        HashMap<String, Object> map = (HashMap<String, Object>) o;
        int num = (int) map.get("num");
        Date date = (Date) map.get("lastDate");
        long timeDifference = ((new Date().getTime() - date.getTime()) / 60 / 1000);
        if (num == 3 && timeDifference < 30 ) {
            return false;
        }
        return true;
    }
    public boolean checkLock2(String username) {
        Object o = redisTemplate.opsForValue().get("loginCheckLock" + username);
        if (o == null) {
            return true;
        }
        HashMap<String, Object> map = (HashMap<String, Object>) o;
        int num = (int) map.get("num");
        log.info("checkNum222================================="+num);
        if (num >= 5) {
            return false;
        }
        return true;
    }
    public void addFailNum(String username) {
        Object o = redisTemplate.opsForValue().get("loginCheckLock" + username);
        HashMap<String,Object> map = null;
        int num= 0;
        if(o==null) {
            map = new HashMap<String,Object>();
        }else {
            map  = (HashMap<String, Object>) o;
            num  = (int) map.get("num");
//            Date date = (Date) map.get("lastDate");
//            long timeDifference = ((new Date().getTime()-date.getTime())/60/1000);
//            if(timeDifference>=30) {
//                num=0;
//            }
        }
        map.put("num", num+1);
        map.put("lastDate", new Date());
        redisTemplate.opsForValue().set("loginCheckLock" + username,map);
    }

    /**
     * 清除key
     * @param username
     */
    public void cleanFailNum(String username) {
        redisTemplate.delete("loginCheckLock" + username);
    }

    /**
     * 解锁子账号接口
     * @return
     */
    @RequestMapping(method = RequestMethod.GET,value = "/unlock")
    public ServerResponse unlock(String username){
        cleanFailNum(username);
        SubAccount subAccount = new SubAccount();
        subAccount.setStatus(0);
        subAccount.setUsername(username);
        Integer i = subAccountService.updateSubAccountNew(subAccount);
        if(i == null){
            return ServerResponse.createByErrorMessage("解锁失败");
        }else{
            if(i > 0){
                return ServerResponse.createBySuccessMessage("解锁成功");
            }else {
                return ServerResponse.createByErrorMessage("解锁失败");
            }
        }
    }

    public String getLocalIp(HttpServletRequest request) {
        String remoteAddr = request.getRemoteAddr();
        String forwarded = request.getHeader("X-Forwarded-For");
        String realIp = request.getHeader("X-Real-IP");

        String ip = null;
        if (realIp == null) {
            if (forwarded == null) {
                ip = remoteAddr;
            } else {
                ip = remoteAddr + "/" + forwarded.split(",")[0];
            }
        } else {
            if (realIp.equals(forwarded)) {
                ip = realIp;
            } else {
                if(forwarded != null){
                    forwarded = forwarded.split(",")[0];
                }
                ip = realIp + "/" + forwarded;
            }
        }
        System.out.println("ip为+++++++++++++++++{+"+ip+"+}+++++++++");
        log.info("ip为+++++++++++++++++{}+++++++++",ip);
        return ip;
    }


    @SysLogAnnotation(value = "web端登录",userType = 2)
    @RequestMapping(method = RequestMethod.POST,value = "/login")
    public ServerResponse<HashMap> loginAdministrator(@RequestBody HashMap<String,Object> params,HttpServletRequest request)throws ServletException, IOException {
        MapValueHelper mapValueHelper = new MapValueHelper(params);
        String password = mapValueHelper.getString("password");
        String username = mapValueHelper.getString("username");
        String imageText = mapValueHelper.getString("imageText");
        //校验验证码是否正确
        String text = (String)redisTemplate.opsForValue().get("text");
        if(text == null || "".equals(text)){
            return ServerResponse.createByErrorMessage("验证码已过期!");
        }
        if (!text.equalsIgnoreCase(imageText)) {
            return ServerResponse.createByErrorMessage("验证码输入错误!");
        }
        QueryWrapper qw = new QueryWrapper();
        qw.eq("username",username);
        SubAccount subAccount1 = subAccountService.getOne(qw);
        //判断ip
        Administrator byAdministratorName = administratorService.findByAdministratorName(username);
        if(byAdministratorName != null){
            String syAdminLoginIp = syAdminLoginIpMapper.selectAdminIp();
            if (!getLocalIp(request).equals(syAdminLoginIp)) {
                return ServerResponse.createByErrorCodeMessage(400, "此IP限制登录,请联系开发人员");
            }
        }
        if(subAccount1 != null){
            if(subAccount1.getIsVerifyIp() == 1){
                List<String> syAdminLoginIps = syAdminLoginIpService.loginIpList(subAccount1.getCompanyId());
                if(!syAdminLoginIps.contains(getLocalIp(request))){
                    return ServerResponse.createByErrorCodeMessage(400,"此IP限制登录,请联系管理员");
                }
            }
        }
        if(subAccount1 != null){
            if(subAccount1.getStatus() != 0){
                return ServerResponse.createByErrorCodeMessage(400,"账号已锁定，请联系管理员");
            }
        }
        //判断登录次数 处理
        if(!username.equals(admin)){
            if(!checkLock(username)) {
                //3次锁定30分钟
                return ServerResponse.createByErrorCodeMessage(400,"账号密码错误，连续3次错误系统锁定30分钟");
            }
            //5次锁定
            if(!checkLock2(username)) {
                SubAccount subAccount = new SubAccount();
                subAccount.setStatus(1);
                subAccount.setUsername(username);
                Integer i = subAccountService.updateSubAccountNew(subAccount);
                return ServerResponse.createByErrorCodeMessage(400,"该账号已被锁定，请联系管理员。");
            }
        }

        String pwd = MD5Utils.createMD5(password);
        params.put("password",pwd);
        Administrator administrator2 = administratorService.findByAdministratorNameAndAdministratorPassword(params);

        UserVO userVO = new UserVO();
        HashMap<String, Object> hashMap = new HashMap<>();
        if (administrator2 == null) {
            SubAccount req = new SubAccount();
            req.setUsername(username);
            req.setPassword(pwd);
            List<SubAccount> subAccounts = subAccountService.selectSubAccountList(req);
            if (CollectionUtils.isEmpty(subAccounts)) {
                //redis登陆次数+1
                if(!username.equals(admin)) {
                    addFailNum(username);
                    Object o = redisTemplate.opsForValue().get("loginCheckLock" + username);
                   if(o != null){
                       HashMap<String, Object> map = (HashMap<String, Object>) o;
                       int num = (int) map.get("num");
                       if(num == 3){
                           return ServerResponse.createByErrorMessage("账号密码错误，连续3次错误系统锁定30分钟");
                       }else if(num == 5){
                           return ServerResponse.createByErrorMessage("该账号已被锁定，请联系管理员。");
                       }else{
                           return ServerResponse.createByErrorMessage("账号密码错误，连续3次错误系统锁定30分钟，再错2次将永久锁定，须联系管理员");
                       }
                   }
                }
            } else {
                SubAccount subAccount = subAccounts.get(0);
                userVO.setUserId(subAccount.getUserId());
                userVO.setRoleId(subAccount.getRoleId());
                userVO.setCompanyId(subAccount.getCompanyId());
                hashMap.put("role", subAccount.getRoleId());
                hashMap.put("nick_name", subAccount.getNickName());
            }
        } else {
            userVO.setUserId(administrator2.getAdminitratorId());
            userVO.setRoleId(0);
            userVO.setCompanyId(administrator2.getCompanyId());
        }

        //判断联盟是否过期提醒
        List<TaobaoScheme> taoBaoPlanList = taoBaoPlanService.findTaoBaoPlanAll(null);
        List<TaobaoScheme> tbList = new ArrayList<>();
        StringBuffer str = new StringBuffer();
        for (TaobaoScheme taoBaoPlan: taoBaoPlanList) {
            long up_time = taoBaoPlan.getExpireTime().getTime();//到期时间
            long time = up_time - System.currentTimeMillis();//获取剩余时间
            if ( time/(24*3600*1000) <= 3){
                tbList.add(taoBaoPlan);
            }
        }
        str.append("您有"+tbList.size()+"个联盟账号即将过期");
        if(tbList.size() >0){
            hashMap.put("pastDue",str);
        }
        //生成token
        String token = Jwts.builder()
                .setSubject(JSONObject.toJSONString(userVO))
                .setExpiration(DateTime.now().plusDays(1).toDate())
                //.setExpiration(DateTime.now().plusMinutes(1).toDate())
                .signWith(SignatureAlgorithm.HS512, ConstantKey.SIGNING_KEY)
                .compact();
        hashMap.put("token", ApiEnum.JWT_KEY + token);
        //hashMap.put("menu", Menth(userVO));//登陆时未用到
        //清除redis登录次数
        if(!username.equals(admin)) {
            cleanFailNum(username);
        }
        return ServerResponse.createBySuccess("登陆成功", hashMap);
    }

    /**
     * 注册
     *
     * @param parms
     * @return
     */
    @SysLogAnnotation(value = "注册",userType = 2)
    @RequestMapping(method = RequestMethod.POST, value = "/register")
    public ServerResponse register(@RequestBody HashMap<String, Object> parms) {
        return administratorService.insertUserNameAndPwd(parms);
    }

    /**
     * 修改密码
     */
    @SysLogAnnotation(value = "修改密码",userType = 2)
    @RequestMapping(method = RequestMethod.POST, value = "/uppwd")
    public ServerResponse uppwd(@RequestBody HashMap<String, Object> parms) {
        MapValueHelper mapValueHelper = new MapValueHelper(parms);
        String username = mapValueHelper.getString("username");
        String oldPassword = mapValueHelper.getString("oldPassword");
        String password = mapValueHelper.getString("password");
        Administrator administrator1 = administratorService.findByAdministratorName(username);
        String pwd = MD5Utils.createMD5(oldPassword);
        if (administrator1 == null){
            SubAccount account = new SubAccount();account.setUsername(username);
            SubAccount subAccount = subAccountService.selectSubAccountList(account).get(0);
            if (subAccount == null){
                return ServerResponse.createByErrorMessage("该账户名不存在！");
            }else {
                if (!subAccount.getPassword().equals(pwd)) {
                    return ServerResponse.createByErrorMessage("旧密码错误");
                }
                String newpwd = MD5Utils.createMD5(password);
                account.setPassword(newpwd);
                int i = subAccountService.updatePwd(account);
                if(i > 0 ){
                    return ServerResponse.createBySuccess("修改成功");
                }else {
                    return ServerResponse.createByError();
                }
            }
        }
        if (!administrator1.getAdminitratorPassword().equals(pwd)) {
            return ServerResponse.createByErrorMessage("旧密码错误");
        }

        String newpwd = MD5Utils.createMD5(password);
        parms.put("password", newpwd);
        int update = administratorService.update(parms);
        if (update > 0) {
            return ServerResponse.createBySuccess("修改成功");
        } else {
            return ServerResponse.createByError();
        }
    }

    public Object Menth(UserVO userVO) {
        UserMenuVo userMenuVo = new UserMenuVo();
        userMenuVo.setText("返利后台");
        userMenuVo.setGroup(false);
        List<Object> menuInfo = new ArrayList<>();
        if (userVO.getRoleId() != null && userVO.getRoleId() != 0) {
            RoleInfoMenus req = new RoleInfoMenus();
            req.setRoleinfoId(userVO.getRoleId());
            List<RoleInfoMenus> menuInfos = roleInfoMenusService.selectRoleInfoMenusList(req);
            List<Integer> menuList = new ArrayList<>();
            for (RoleInfoMenus menuInfo1 : menuInfos) {
                menuList.add(menuInfo1.getMenusId());
            }
            //查询菜单，排序
            QueryWrapper<MenuInfo> queryWrapper = new QueryWrapper<>();
            queryWrapper.in("id",menuList);
            queryWrapper.orderByAsc("sort_id");
            List<MenuInfo> list = menuInfoService.list(queryWrapper);
            for(MenuInfo menu:list){
                menuInfo.add(JSONObject.parse(menu.getMenuUrl()));
            }

        } else {
            List<MenuInfo> menuInfo2 = menuInfoService.selectMenuInfoList(null);
            for (MenuInfo menuInfo1:menuInfo2){
                if(menuInfo1.getOrderId()==0){
                    menuInfo.add(JSONObject.parse(menuInfo1.getMenuUrl()));
                }
            }
        }
        userMenuVo.setChildren(menuInfo);

        List<UserMenuVo> lIst = new ArrayList<>();
        lIst.add(userMenuVo);
        return lIst;
    }

    @Autowired
    IRoleInfoMenusService roleInfoMenusService;
    @Autowired
    IMenuInfoService menuInfoService;


}
